from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View

# from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import re
import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from .models import *

import redis

host = '127.0.0.1'
port = 6379
r = redis.Redis(host=host, port=port)

# 构建钉钉登录的回调地址
import hmac
import base64
from hashlib import sha256
import urllib

from .myser import UserSerializers

import jwt
from django.utils.deprecation import MiddlewareMixin


# 自定义中间件类
class MyMiddleWare(MiddlewareMixin):

    # 请求之前
    def process_request(self, request):
        # uid = request.GET.get('uid')
        # web_jwt = request.GET.get('jwt',None)
        #
        # if (web_jwt == None):
        #     return HttpResponse('您的操作不当')
        # else:
        #     decode_jwt = jwt.decode(web_jwt, '123', algorithms=['HS256'])
        #     if(decode_jwt['uid'] != str(uid)):
        #         return HttpResponse('您篡改了用户id')
        pass

    # 模板渲染之前
    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    # 请求之后
    def process_response(self, request, response):
        return response


# 装饰器
def my_decorator(func):
    def wrapper(request, *args, **kwargs):
        uid = request.GET.get('uid')
        web_jwt = request.GET.get('jwt', None)

        if (web_jwt == None):
            return HttpResponse('您的操作不当')
        else:
            decode_jwt = jwt.decode(web_jwt, '123', algorithms=['HS256'])
            if (decode_jwt['uid'] != str(uid)):
                return HttpResponse('您篡改了用户id')
        return func(request, *args, **kwargs)

    return wrapper


# 类装饰器调用
from django.utils.decorators import method_decorator


# 用户信息类
class UserInfo(APIView):
    @method_decorator(my_decorator)
    def get(self, request):
        uid = request.GET.get('uid')
        user = User.objects.get(id=int(uid))
        # 序列化对象
        user_ser = UserSerializers(user)
        return Response(user_ser.data)


# 更新用户数据(vedio字段)
class UpdateVedio(APIView):

    def post(self, request):
        uid = request.POST.get('uid')
        vedio = request.POST.get('vedio')
        print(uid, vedio)

        # 查询数据
        user = User.objects.get(id=int(uid))
        print(user)
        user.vedio = vedio
        user.save()

        return Response({
            'code': 200,
            'message': '更新成功'
        })


# 更新用数据(头像字段)
class UpdateUser(APIView):

    def post(self, request):
        img = request.POST.get('img')
        uid = request.POST.get('uid')

        # 查询数据
        user = User.objects.get(id=int(uid))
        user.img = img
        user.save()

        return Response({
            'code': 200,
            'message': '更新成功'
        })


# 导入七牛云接口
from qiniu import Auth


# 定义七牛云存储接口
class QiNiu(APIView):

    def get(self, request):
        # 定义密钥
        q = Auth('tWrLuodRCMpZKtCwRnPwFbiwN2zkRzNDpTWi8lC4',
                 'PW_ORc0tqDr4UH55Rn_ExdF62GXRyA3nBT18LrfT')

        # 指定上传空间
        token = q.upload_token('testaction')
        res = {}
        res['token'] = token
        return Response(res)


# 上传图片
class UploadFile(View):

    def post(self, request):
        # 获取图片
        img = request.FILES.get('file')
        imagename = img.name
        # 获取用户信息
        username = request.POST.get('username')
        print(imagename, username)
        user = User.objects.filter(username=username).first()
        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '', imagename), 'wb')
        # 写入
        for chunk in img.chunks():
            f.write(chunk)
        f.close()
        # 打开图片
        im = Image.open("./static/upload/" + imagename)
        # 生成画笔对象
        draw = ImageDraw.Draw(im)
        # 修改图片
        myfont = ImageFont.truetype(font='C:/font/STLITI.TTF', size=30)
        draw.text((0, 0), username, fill=(76, 234, 124, 180), font=myfont)
        im.save('./static/upload/' + imagename)
        # 修改图片名
        newimgename = user.username + re.findall(r'(.jpg|.png|.JPEG|.jpeg)', imagename)[0]
        print(newimgename)
        # 删除旧图
        try:
            os.remove(UPLOAD_ROOT + '\\' + newimgename)
        except Exception as e:
            print(e)
        # 修改图片名称
        os.rename(UPLOAD_ROOT + '\\' + imagename, UPLOAD_ROOT + '\\' + newimgename)
        # 将图片名保存到库中
        user.img = newimgename
        user.save()

        return HttpResponse(json.dumps({'filename': newimgename}, ensure_ascii=False), content_type='application/json')


# 修改密码
class Update(APIView):

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        apassword = request.data.get('apassword')
        print(username, password, apassword)
        user = User.objects.filter(username=username, password=password)
        if user:
            user.update(password=apassword)
            return Response({
                'code': 200,
                'message': '修改成功'
            })
        else:
            return Response({
                'code': 203,
                'message': '密码输入错误，请重新输入！'
            })


# 构造钉钉回调方法
def ding_back(request):
    # 获取code
    code = request.GET.get("code")
    print(code)

    t = time.time()
    # 时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret = 'KcABdDAOBuiUMI7VRftnqTrI1q3CvOeAG4Qnlu4fcYuGbgWaFDIhbz1wqhSgfH-N'
    # 构造签名
    signature = base64.b64encode(
        hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
    # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code': code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
        signature.decode("utf-8")) + "&timestamp=" + timestamp + "&accessKey=dingoawcbhhfj9bdsvwprj",
                        data=json.dumps(payload), headers=headers)

    res_ = json.loads(res.text)
    name = res_['user_info']['nick']
    # 判断用户是否登陆过
    user = User.objects.filter(username=str(name)).first()
    if user:
        ding_id = user.username
        uid = user.id
    else:
        # 手动创建账号
        User.objects.create(username=str(name), password='')
        user = User.objects.filter(username=str(name)).first()
        ding_id = user.username
        uid = user.id
    print(ding_id, uid)
    return redirect('http://localhost:8080?sina_id=' + ding_id + '&uid=' + str(uid))


# 新浪微博回调
def weibo(request):
    # 获取code
    code = request.GET.get('code')
    # 定义微博认证地址
    access_token_url = "https://api.weibo.com/oauth2/access_token"
    # 参数
    res = requests.post(
        url=access_token_url,
        data={
            'client_id': '1136699019',
            'client_secret': '809be555c0fc7816d987f694cc649e94',
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': 'http://127.0.0.1:8000/weibo'
        }
    )
    # 将交换到的字符串转换成json格式
    res = json.loads(res.text)

    # 换取新浪微博的昵称 json
    result = requests.get('https://api.weibo.com/2/users/show.json', params={
        'access_token': res['access_token'], 'uid': res['uid']
    })
    print(result.text)
    result = json.loads(result.text)
    # 判断该用户是否登陆过
    user = User.objects.filter(username=str(result['name'])).first()
    if user:
        sina_id = user.username
        user_id = user.id
    else:
        # 手动创建账号
        user = User.objects.create(username=str(result['name']), password='')
        sina_id = result['name']
        # 查询
        user = User.objects.filter(username=str(result['name'])).first()
        user_id = user.id

    return redirect('http://localhost:8080?sina_id=' + sina_id + '&uid=' + str(user_id))


class MyCode(View):
    # 定义随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, G, B)

    # 获取验证码试图
    def get(self, request):
        # 画布
        img_size = (120, 50)
        # 定义画图对象
        image = Image.new('RGB', img_size, 'white')
        # 定义画笔对象
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义随机字符串
        source = '0123456789'
        # 容器
        code_str = ''
        # 定义字体
        my_font = ImageFont.truetype(font="C:\\font\\STHUPO.TTF", size=20)
        for i in range(4):
            # 获取随机颜色
            text_color = self.get_random_color()
            # 获取随机字符串长度下标
            tmp_num = random.randrange(len(source))
            # 获取字符集
            random_str = source[tmp_num]
            # 添加到容器中
            code_str += random_str
            # 将字符串添加到画布中去
            draw.text((10 + 30 * i, 20), random_str, text_color, font=my_font)
        # 建立缓存区
        buf = io.BytesIO()
        # 保存图片
        image.save(buf, 'png')

        # 将验证码存到redis库中
        r.set('code', code_str)

        # 将验证码存到session中
        request.session['session_code'] = code_str

        return HttpResponse(buf.getvalue(), 'image/png')


# md5加密
def make_password(mypwd):
    # 生成md5对象
    md5 = hashlib.md5()
    # 定义加密对象
    reg_str = str(mypwd)
    # 转码
    reg_utf8 = reg_str.encode(encoding='utf-8')
    # 加密
    md5.update(reg_utf8)
    # 生成密钥串
    md5_server = md5.hexdigest()

    return md5_server


# 注册
class Register(APIView):

    def get(self, request):
        username = request.GET.get('username')
        password = request.GET.get('password')
        mycode = request.GET.get('mycode')
        print(username, password, mycode)
        if not all([username, password, mycode]):
            return Response({
                'code': 203,
                'data': '数据信息不完整'
            })
        else:
            # 获取redis中的验证码，并进行比对
            recode = r.get('code')
            recode = recode.decode('utf8')
            print(recode)

            # 获取session中的验证码，并进行比对
            # siscode = request.session.get('session_code')
            # print(siscode)
            if mycode != recode:
                return Response({
                    'code': 202,
                    'data': '验证码输入有误'
                })

            else:
                user = User.objects.filter(username=username).first()
                if user:
                    return Response({
                        'code': 201,
                        'data': '该用户名已存在，不可重复注册'
                    })

                else:
                    User.objects.create(username=username, password=make_password(password))
                    return Response({
                        'code': 200,
                        'data': '注册成功'
                    })


class Login(APIView):

    def get(self, request):
        username = request.GET.get('username')
        password = request.GET.get('password')

        user = User.objects.filter(username=username, password=make_password(password)).first()
        if user:
            # 加入jwt令牌机制
            # 进行编码
            encode_jwt = jwt.encode({'uid': str(user.id)}, '123', algorithm='HS256')
            # 解码操作
            # 强转
            encode_str = str(encode_jwt, 'utf8')
            return Response({
                'code': 200,
                'message': '登录成功',
                'username': user.username,
                'uid': user.id,
                'filename': user.img,
                'jwt': encode_str,
                'type': user.type
            })
        else:
            return Response({
                'code': 203,
                'message': '用户名或密码输入错误'
            })
